<?php

namespace api\components;

use backend\util\httpcurl\HttpCurl;
use Yii;
use yii\base\Component;

/**
 * 公众号方法
 * Class WeChatPublic
 * @package api\components
 */
class WeChatPublic extends Component
{
    public $redis;

    public $WxAppId;

    public $WxSecret;

    public $accessToken;

    private $requestCodeURL = 'https://open.weixin.qq.com/connect/oauth2/authorize';

    private $apiURL = 'https://api.weixin.qq.com/cgi-bin';

    private $oauthApiURL = 'https://api.weixin.qq.com/sns';


    public function __construct()
    {
        parent::__construct();

        $this->redis = Yii::$app->redis;

        $this->WxAppId = Yii::$app->params['WxPublic']['appid'];
        $this->WxSecret = Yii::$app->params['WxPublic']['appsecret'];
    }

    /**
     * 获取access_token
     * @param string $type
     * @param null $code
     * @return mixed|string
     * @throws \Exception
     */
    public function getAccessToken($type = 'client', $code = null)
    {
        switch ($type) {
            case 'client':
                $request = $this->apiURL . '/token?grant_type=client_credential&appid=' . $this->WxAppId . '&secret=' . $this->WxSecret;
                break;
            case 'code':
                $request = $this->oauthApiURL . '/oauth2/access_token?grant_type=authorization_code&appid=' . $this->WxAppId . '&secret=' . $this->WxSecret . '&code=' . $code;
                break;
            default:
                throw new \Exception('不支持的类型');
                break;
        }

        if ($type == 'client') {

            //全局性access_token
            $authName = 'wechat_access_token_' . $type . '_' . $this->WxAppId;
            $expireKey = 'wechat_access_token_expire_' . $type . '-' . $this->WxAppId;

            $expireValue = $this->redis->get($expireKey);

            if ($expireValue < time()) {
                $this->redis->del($authName);
                $this->redis->del($expireKey);

                $json_encode_str = HttpCurl::http_get($request);
                $json_decode_obj = json_decode($json_encode_str, true);

                $error = isset($json_decode_obj['errcode']) ? $json_decode_obj['errcode'] : false;
                $access_token = isset($json_decode_obj['access_token']) ? $json_decode_obj['access_token'] : '';
                if (!$error) {
                    $expire = 6200;
                    $this->redis->set($authName, $access_token);
                    $this->redis->expire($authName, $expire);

                    $this->redis->set($expireKey, time() + $expire);

                    return $access_token;
                }

            } else {
                return $this->redis->get($authName);
            }

        } else {
            //网页版授权
            $json_encode_str = HttpCurl::http_get($request);
            $json_decode_obj = json_decode($json_encode_str, true);
            return $json_decode_obj;
        }
    }

    /**
     * 拼接url
     * @param $redirect_uri
     * @param null $state
     * @param string $scope
     * @return string
     */
    public function getRequestCodeURL($redirect_uri, $state = null, $scope = 'snsapi_userinfo')
    {
        $query = [
            'appid' => $this->WxAppId,
            'redirect_uri' => $redirect_uri,
            'response_type' => 'code',
            'scope' => $scope,
        ];

        if (!is_null($state) && preg_match('/[a-zA-Z0-9]+/', $state)) {
            $query['state'] = $state;
        }
        $query = http_build_query($query);
        return "{$this->requestCodeURL}?{$query}#wechat_redirect";
    }

    /**
     * 获取用户信息
     * @param $openid
     * @param $accessToken
     * @param string $lang
     * @return mixed
     */
    public function getUser($openid, $accessToken, $lang = 'zh_CN')
    {
        $query = [
            'access_token' => $accessToken,
            'openid'       => $openid,
            'lang'         => $lang,
        ];
        $url = $this->oauthApiURL . '/userinfo?' . http_build_query($query);
        $msg = HttpCurl::http_get($url);
        return json_decode($msg, true);
    }

    /**
     * 设置菜单
     * @param $map
     * @return mixed
     */
    public function setMenu($map)
    {
        $token = $this->getAccessToken();
        $request = $this->apiURL . "/menu/create?access_token={$token}";
        $res = HttpCurl::http_post($request, $map);
        return json_decode($res, true);
    }

    /**
     * 获取菜单
     * @return mixed
     */
    public function getMenu()
    {
        $token = $this->getAccessToken();
        $request = $this->apiURL . "/menu/get?access_token={$token}";
        $res = HttpCurl::http_get($request);
        return json_decode($res, true);
    }

}